using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using backend.Common;
using backend.Data;
using backend.Models;
using backend.Models.Dtos;
using backend.Services;
using Microsoft.EntityFrameworkCore;

namespace backend.Repositories
{
    public class RepairRequestRepo : BaseRepo<CampusFacilityRepairManagementDbContext, RepairRequest>
    {
        private readonly IMapper _mapper;
        private readonly CampusFacilityRepairManagementDbContext _context;
        public RepairRequestRepo(CampusFacilityRepairManagementDbContext context, IMapper mapper) : base(context)
        {
            _mapper = mapper;
            _context = context;
        }

        public async Task<RepairRequest> CreateRepairRequestAsync(RepairRequestCreateDto request)
        {
            var fcName = _context.FirstClasses
                               .Where(fc => fc.FcId == request.Area)
                               .Select(fc => fc.FcName)
                               .FirstOrDefault();

            if (fcName == null)
            {
                throw new ArgumentException("Invalid area.");
            }

            var scName = _context.SecondClasses
                               .Where(sc => sc.ScId == request.Location)
                               .Select(sc => sc.ScName)
                               .FirstOrDefault();

            if (scName == null)
            {
                throw new ArgumentException("Invalid location.");
            }

            var newRequest = new RepairRequest
            {
                UId = request.UserID,
                RDescription = request.Description,
                RPicture = await SaveImageAsync(request.Image), // 假设有一个方法来保存图片并返回路径
                RLocation = fcName + " " + scName + " " + request.DetailedLocation,
                RConvenientTime = request.ExpectedTime,
                RState = "未审核",
                FId = request.FaultTypeID, // 假设有一个方法来获取故障类型的ID
                FcId = request.Area,
                RTime = DateTime.Now
            };

            await DbSet.AddAsync(newRequest);
            await Context.SaveChangesAsync();

            return newRequest;
        }

        public async Task<RepairRequestDto> GetRepairRequestByIdAsync(int orderId)
        {
            var repairRequest = await DbSet.FirstOrDefaultAsync(r => r.RId == orderId);

            if (repairRequest == null)
            {
                throw new ArgumentException("Order not found.");
            }

            var user = await _context.Users.FirstOrDefaultAsync(u => u.UId == repairRequest.UId);
            var staff = await _context.MaintenanceMen.FirstOrDefaultAsync(s => s.MId == repairRequest.MId);
            var fault = await _context.Failures.FirstOrDefaultAsync(f => f.FId == repairRequest.FId);

            if (user == null)
            {
                throw new ArgumentException("User not found.");
            }

            if (fault == null)
            {
                throw new ArgumentException("Fault type not found.");
            }

            var dto = new RepairRequestDto
            {
                UserID = user.UId,
                UserName = user.UName,
                UserPhone = user.UContact,
                StaffID = staff?.MId,
                StaffName = staff?.MIdNavigation.UName,
                StaffPhone = staff?.MIdNavigation.UContact,
                Description = repairRequest.RDescription,
                Image = repairRequest.RPicture,
                DetailedLocation = repairRequest.RLocation, // 假设在 RepairRequest 中有 ScnName 属性
                FaultType = fault.FName,
                ExpectedTime = repairRequest.RConvenientTime,
                Status = repairRequest.RState,
                StartTime = repairRequest.RTime,
                FixStartTime = repairRequest.RStartTime,
                EndTime = repairRequest.REndTime,
                ResponseTime = repairRequest.RResponseTime,
                ServiceQuality = repairRequest.RQuality,
                ServiceAttitude = repairRequest.RAttitude
            };

            return dto;
        }

        public async Task<List<RepairRequestListDto>> GetRepairRequestListAsync(int page, int number, string? specialize, string userID, string role, string? area, string? status)
        {
            var query = DbSet.AsQueryable();
            query = query.Include(r => r.Fc) // 包含 FirstClass
                         .Include(r => r.FIdNavigation); // 包含 Failure

            // 根据用户角色过滤
            if (!string.IsNullOrEmpty(role))
            {
                if (role == "0")
                {
                    query = query.Where(r => r.UId == userID);
                }
                else if (role == "1" && !string.IsNullOrEmpty(specialize))
                {
                    var profession = await _context.Professions.Where(p => p.PId == specialize).FirstOrDefaultAsync();
                    if (profession == null)
                    {
                        throw new ArgumentException("Invalid specialize.");
                    }
                    var faultTypeList = profession.Failures.Select(f => f.FId);
                    query = query.Where(r => faultTypeList.Contains(r.FId));
                }
            }

            if (!string.IsNullOrEmpty(area))
            {
                var fc = await _context.FirstClasses.Where(fc => fc.FcId == area).FirstOrDefaultAsync();
                if (fc == null)
                {
                    throw new ArgumentException("Invalid area.");
                }
                query = query.Where(r => r.FcId == area);
            }

            if (!string.IsNullOrEmpty(status))
            {
                query = query.Where(r => r.RState == status);
            }

            // 分页
            var skipCount = (page - 1) * number;
            var takeCount = number;
            var results = await query
                .OrderByDescending(r => r.RTime)
                .Skip(skipCount)
                .Take(takeCount)
                .ToListAsync();

            var dtos = results.Select(r => new RepairRequestListDto
            {
                OrderID = r.RId, // 直接使用整数形式的订单ID
                Area = r.Fc?.FcName ?? "Unknown Area", // 防止Fc为null的情况
                Location = r.RLocation ?? "", // 防止RLocation为null的情况
                FaultType = r.FIdNavigation?.FName ?? "Unknown Fault Type", // 防止FIdNavigation为null的情况
                Status = r.RState ?? "", // 防止RState为null的情况
                StartTime = r.RTime, // 防止RTime为null的情况
                AreaIsDeleted = r.Fc?.FcStopUsing ?? false // 防止Fc为null的情况
            }).ToList();

            return dtos;
        }

        public async Task<bool> UpdateRepairRequestAsync(int orderId, UserRole userRole, string userID, string? status, RepairRequestUpdateDto.RatingDto? rating, string? userEvaluate)
        {
            var existingOrder = await DbSet.FindAsync(orderId);
            if (existingOrder == null)
            {
                throw new KeyNotFoundException($"Order with ID '{orderId}' not found.");
            }
            var sourceStatus = StatusMapper.MapStatus(existingOrder.RState);


            if (!string.IsNullOrEmpty(status))
            {
                // 检查状态转移是否合法
                var destStatus = StatusMapper.MapStatus(status);
                if (!OrderStatusTransitions.Transitions.TryGetValue(sourceStatus, out var allowedStatuses) || !allowedStatuses.Contains(destStatus))
                {
                    throw new InvalidOperationException($"Invalid status transition from '{existingOrder.RState}' to '{status}'.");
                }
                // 检查用户是否有权限进行此操作
                if (!UserRolePermissions.Permissions.TryGetValue(userRole, out var allowedActions) || !allowedActions.Contains(destStatus))
                {
                    throw new UnauthorizedAccessException($"User with role '{userRole}' does not have permission to update the order status to '{status}'.");
                }

                existingOrder.RState = status;
                if (destStatus == OrderStatus.WaitingForRepair) {
                    existingOrder.RStartTime = DateTime.Now;
                    existingOrder.MId = userID;
                }
                if (destStatus == OrderStatus.WaitingForAssignment) { 
                    existingOrder.MId = null;
                }
                await Context.SaveChangesAsync();
                return true;
            }


            if (rating != null && IsValidRating(rating) && userRole == UserRole.NormalUser)
            {
                existingOrder.RQuality = rating.ServiceQuality;
                existingOrder.RAttitude = rating.ServiceAttitude;
                existingOrder.RResponseTime = rating.ResponseTime;

                await Context.SaveChangesAsync();
                return true;
            }

            if (userEvaluate != null && userRole == UserRole.NormalUser)
            {
                if (userEvaluate.Length > 256) {
                    throw new ArgumentException("The length of the evaluation content exceeds 256 characters.");
                }
                existingOrder.REvaluate = userEvaluate;
                await Context.SaveChangesAsync();
                return true;
            }

            return false;
        }

        private async Task<string> SaveImageAsync(IFormFile? image)
        {
            // 检查是否上传了图片
            if (image == null || image.Length == 0)
            {
                throw new ArgumentException("No image provided.");
            }

            // 允许的图片格式
            var allowedExtensions = new[] { ".jpg", ".jpeg", ".png", ".gif" };
            var fileExtension = Path.GetExtension(image.FileName).ToLower();

            // 文件类型检查
            if (!allowedExtensions.Contains(fileExtension))
            {
                throw new ArgumentException("Invalid file type. Only .jpg, .jpeg, .png, and .gif files are supported.");
            }

            // 文件大小限制，例如最大为5MB
            long maxSizeInBytes = 5 * 1024 * 1024; // 5MB
            if (image.Length > maxSizeInBytes)
            {
                throw new ArgumentException($"File size exceeds the limit of {maxSizeInBytes} bytes.");
            }

            // 设置图片保存的目录
            string uploadsFolder = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/images");

            // 确保目录存在
            if (!Directory.Exists(uploadsFolder))
            {
                Directory.CreateDirectory(uploadsFolder);
            }

            // 生成唯一的文件名
            string uniqueFileName = Guid.NewGuid().ToString() + fileExtension;

            // 定义图片完整路径
            string filePath = Path.Combine(uploadsFolder, uniqueFileName);

            // 保存图片到指定路径
            using (var fileStream = new FileStream(filePath, FileMode.Create))
            {
                await image.CopyToAsync(fileStream);
            }

            // 返回保存后的图片文件路径，这里假设是相对于根目录的路径
            return $"/images/{uniqueFileName}";
        }

        private bool IsValidRating(RepairRequestUpdateDto.RatingDto rating)
        {
            decimal minValue = 0M;
            decimal maxValue = 5M;
            return rating.ResponseTime >= minValue && rating.ResponseTime <= maxValue &&
                   rating.ServiceQuality >= minValue && rating.ServiceQuality <= maxValue &&
                   rating.ServiceAttitude >= minValue && rating.ServiceAttitude <= maxValue;
        }
    }
}